﻿using CubeCube.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CubeCube.World.Generator
{
    public class WorldSizeRelativeValue
    {
        private enum RelativeTo
        {
            Nothing,
            SizeX,
            SizeY,
            SizeZ,
            SizeXY,
            SizeXZ,
            SizeYZ,
            SizeVolumen
        }

        private RelativeTo relativeTo;
        private float value;
        private string expression;

        public string Expression
        {
            get { return this.expression; }
        }

        public WorldSizeRelativeValue(string expression)
        {
            expression = expression.ToLower().Trim();  //转小写并且删除前后的空格
            this.expression = expression;

            if (expression.IndexOf('*') <= 0)
            {
                if (Char.IsDigit(expression[0]) == true)  // exp:  "0.5"
                {
                    relativeTo = RelativeTo.Nothing;
                    value = float.Parse(expression, System.Globalization.CultureInfo.InvariantCulture);
                }
                else // exp:  "SizeZ"
                {
                    relativeTo = (RelativeTo)System.Enum.Parse(typeof(RelativeTo), expression, true);
                    value = 1.0f;
                }
            }
            else  // exp:   "SizeZ * 0.53"
            {
                string[] strs = expression.Split('*');
                if (strs.Length != 2)
                    throw new Exception("Invalid relative value string: " + expression);

                relativeTo = (RelativeTo)System.Enum.Parse(typeof(RelativeTo), strs[0], true);

                value = float.Parse(strs[1].Trim(), System.Globalization.CultureInfo.InvariantCulture);
            }
        }

        public int EvaluateInt(Chunk.Chunk chunk)
        {
            return (int)Evaluate(chunk);
        }

        //评估真实值,因为这里用chunk代替了原来世界的概念，所以都是乘以CHUNK_SIZE
        public float Evaluate(Chunk.Chunk chunk)
        {
            switch (relativeTo)
            {
                case RelativeTo.Nothing:
                    return value;

                case RelativeTo.SizeX:
                    return Graphics.CHUNK_SIZE * value;
                case RelativeTo.SizeY:
                    return Graphics.CHUNK_SIZE * value;
                case RelativeTo.SizeZ:
                    return Graphics.CHUNK_SIZE * value;

                case RelativeTo.SizeXY:
                    return (Graphics.CHUNK_SIZE * Graphics.CHUNK_SIZE) * value;
                case RelativeTo.SizeXZ:
                    return (Graphics.CHUNK_SIZE * Graphics.CHUNK_SIZE) * value;
                case RelativeTo.SizeYZ:
                    return (Graphics.CHUNK_SIZE * Graphics.CHUNK_SIZE) * value;

                case RelativeTo.SizeVolumen:
                    return (Graphics.CHUNK_SIZE * Graphics.CHUNK_SIZE * Graphics.CHUNK_SIZE) * value;
            }

            return 0;
        }

    }
}
